package com.wangsd.web.weixin.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wangsd.common.component.WxComponentService;
import com.wangsd.web.weixin.entity.WxMessage;
import com.wangsd.web.weixin.entity.WxTemplate;
import com.wangsd.web.weixin.mapper.WxTemplateMapper;
import com.wangsd.web.weixin.service.TemplateService;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.WxMpTemplateMsgService;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import me.chanjar.weixin.open.api.WxOpenComponentService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Service
public class TemplateServiceImpl implements TemplateService {

    @Autowired
    WxComponentService wxComponentService;

    @Resource
    WxTemplateMapper wxTemplateMapper;

    @Override
    public void sendTemplate(WxMessage message, String openId, String templateId, String appId) throws WxErrorException {
        WxOpenComponentService wxOpenComponentService = wxComponentService.getWxOpenComponentService();
        WxMpService wxMpService = wxOpenComponentService.getWxMpServiceByAppid(appId);
        WxMpTemplateMsgService wxMpTemplateMsgService = wxMpService.getTemplateMsgService();
        templateId = this.getTemplateId(wxMpTemplateMsgService, templateId, appId);
        //接收人，消息id
        WxMpTemplateMessage wmtm = WxMpTemplateMessage.builder()
                .toUser(openId)
                .templateId(templateId)
                .build();
        wmtm = doParams(wmtm, message);
        try {
            //发送消息
            wxMpTemplateMsgService.sendTemplateMsg(wmtm);
        } catch (WxErrorException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void sendTemplate(WxMessage message, List<String> openIds, String templateId, String appId) throws WxErrorException {
        WxOpenComponentService wxOpenComponentService = wxComponentService.getWxOpenComponentService();
        WxMpService wxMpService = wxOpenComponentService.getWxMpServiceByAppid(appId);
        WxMpTemplateMsgService wxMpTemplateMsgService = wxMpService.getTemplateMsgService();
        templateId = this.getTemplateId(wxMpTemplateMsgService, templateId, appId);
        //接收人，消息id
        WxMpTemplateMessage wmtm = WxMpTemplateMessage.builder()
                .templateId(templateId)
                .build();
        wmtm = doParams(wmtm, message);
        threadSend(wmtm, openIds, wxMpTemplateMsgService);
    }

    private void threadSend(WxMpTemplateMessage wmtm, List<String> openIds, WxMpTemplateMsgService wxMpTemplateMsgService) {
        Integer count = 2000;
        if (openIds.size() <= count) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (String openId : openIds) {
                        try {
                            //发送消息
                            wmtm.setToUser(openId);
                            wxMpTemplateMsgService.sendTemplateMsg(wmtm);
                        } catch (WxErrorException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }, "SendTemplate");
            thread.start();
        } else {
            //计算分成多少组
            Integer group = (openIds.size() % count) == 0 ? openIds.size() / count : (openIds.size() / count) + 1;
            List<List<String>> list = this.averageAssign(openIds, group);
            int i = 0;
            for (List<String> ids : list) {
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        for (String openId : ids) {
                            wmtm.setToUser(openId);
                            try {
                                wxMpTemplateMsgService.sendTemplateMsg(wmtm);
                            } catch (WxErrorException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }, "SendTemplate" + (i++));
                thread.start();
            }
        }
    }

    /**
     * 获取公共模版消息库id转私有模版库的id
     *
     * @param templateId
     * @param appId
     * @return
     */
    private String getTemplateId(WxMpTemplateMsgService wxMpTemplateMsgService, String templateId, String appId) throws WxErrorException {
        QueryWrapper query = new QueryWrapper();
        query.eq("template_key", templateId);
        query.eq("app_id", appId);
        WxTemplate wxTemplate = wxTemplateMapper.selectOne(query);
        if (wxTemplate != null) {//已添加公众号模版消息
            return wxTemplate.getTemplateId();
        } else {
            String privateTemplateId = wxMpTemplateMsgService.addTemplate(templateId);
            //数据库插入记录
            WxTemplate insertMsg = new WxTemplate();
            insertMsg.setTemplateKey(templateId);
            insertMsg.setAppId(appId);
            insertMsg.setTemplateId(privateTemplateId);
            wxTemplateMapper.insert(insertMsg);
            return privateTemplateId;
        }
    }

    /**
     * 组装微信模版消息内容
     *
     * @param wmtm
     * @param message
     * @return
     */
    private WxMpTemplateMessage doParams(WxMpTemplateMessage wmtm, WxMessage message) {
        //消息参数
        if (!StringUtils.isEmpty(message.getFirst()))
            wmtm.addData(new WxMpTemplateData("first", message.getFirst()));
        if (!StringUtils.isEmpty(message.getKeyword1()))
            wmtm.addData(new WxMpTemplateData("keyword1", message.getKeyword1()));
        if (!StringUtils.isEmpty(message.getKeyword2()))
            wmtm.addData(new WxMpTemplateData("keyword2", message.getKeyword2()));
        if (!StringUtils.isEmpty(message.getKeyword3()))
            wmtm.addData(new WxMpTemplateData("keyword3", message.getKeyword3()));
        if (!StringUtils.isEmpty(message.getKeyword4()))
            wmtm.addData(new WxMpTemplateData("keyword4", message.getKeyword4()));
        if (!StringUtils.isEmpty(message.getKeyword5()))
            wmtm.addData(new WxMpTemplateData("keyword5", message.getKeyword5()));
        if (!StringUtils.isEmpty(message.getKeyword6()))
            wmtm.addData(new WxMpTemplateData("keyword6", message.getKeyword6()));
        if (!StringUtils.isEmpty(message.getKeyword7()))
            wmtm.addData(new WxMpTemplateData("keyword7", message.getKeyword7()));
        if (!StringUtils.isEmpty(message.getKeyword8()))
            wmtm.addData(new WxMpTemplateData("keyword8", message.getKeyword8()));
        if (!StringUtils.isEmpty(message.getRemark()))
            wmtm.addData(new WxMpTemplateData("remark", message.getRemark()));
        //设置小程序跳转连接
        if(StringUtils.isNotBlank(message.getMiniAppid())){
            WxMpTemplateMessage.MiniProgram program = new WxMpTemplateMessage.MiniProgram();
            program.setAppid(message.getMiniAppid());
            if(StringUtils.isNotBlank(message.getPagePath())){
                program.setPagePath(message.getPagePath());
            }
            wmtm.setMiniProgram(program);
        }
        //跳转url
        if (!StringUtils.isEmpty(message.getUrl()))
            wmtm.setUrl(message.getUrl());

        return wmtm;
    }

    private <T> List<List<T>> averageAssign(List<T> list, int n) {
        List<List<T>> result = new ArrayList<List<T>>();
        int remaider = list.size() % n;  //(先计算出余数)
        int number = list.size() / n;  //然后是商
        int offset = 0;//偏移量
        for (int i = 0; i < n; i++) {
            List<T> value = null;
            if (remaider > 0) {
                value = list.subList(i * number + offset, (i + 1) * number + offset + 1);
                remaider--;
                offset++;
            } else {
                value = list.subList(i * number + offset, (i + 1) * number + offset);
            }
            result.add(value);
        }
        return result;
    }
}
